<?php

/**
 * QPHP
 *
 * Copyright (c) 2022 QPHP
 *
 * @author lbnnbs
 * @copyright Copyright (c) 2022 lbnnbs QPHP (https://gitee.com/lbnnbs/qphp)
 * @license AGPLv3 License
 * 
 * 基础模型
 */
class Model {

    /**
     * 表名
     * @var string 
     */
    static public $table;

    /**
     * 主键ID字段名
     * @var int 
     */
    protected $_id = 'id';

    /**
     * 排序字段名
     * @var string 
     */
    protected $_sort = 'sort';

    /**
     * 可填充字段数组和对应的数据类型
     * 
     * int、str、date、time、datetime、float
     * 
     * array('id' => 'int', 'title' => 'str', 'add_time' => 'datetime')
     * @var array 
     */
    protected $_fillable = null;

    /**
     * 用可填充字段过滤数据
     * @param array $arr
     */
    protected function filter($arr) {
        if ($this->_fillable && is_array($this->_fillable) && is_array($arr)) {

            // 过滤不可填充字段
            $arr = array_filter($arr, function ($k) {
                return array_key_exists($k, $this->_fillable);
            }, ARRAY_FILTER_USE_KEY);

            // 按字段数据类型处理数据
            array_walk($arr, function (&$v, $k) {
                if ($this->_fillable[$k] === 'int') {
                    $v = intval($v);
                }
                if ($this->_fillable[$k] === 'float') {
                    $v = floatval($v);
                }
                if ($this->_fillable[$k] === 'str') {
                    $v = strval($v);
                }
                if ($this->_fillable[$k] === 'date') {
                    $timestamp = strtotime($v);
                    $v = strtotime(date('Y-m-d', $timestamp)) === $timestamp ? $v : null;
                }
                if ($this->_fillable[$k] === 'time') {
                    $timestamp = strtotime(date('Y-m-d') . " {$v}");
                    $v = strtotime(date('Y-m-d H:i:s', $timestamp)) === $timestamp ? $v : null;
                }
                if ($this->_fillable[$k] === 'datetime') {
                    $timestamp = strtotime($v);
                    $v = strtotime(date('Y-m-d H:i:s', $timestamp)) === $timestamp ? $v : null;
                }
            });
        }
        return $arr;
    }

    /**
     * 返回完整的带前缀的表名
     * 
     * @return string
     */
    static public function table() {
        return Db()->tablename(static::$table);
    }
    
    /**
     * 添加记录
     *
     * 表中必须有自增ID字段，如果没有自增ID字段，返回的是上一个有自增ID的插入语句的自增ID。
     * 
     * @param $arr
     * @return false|int
     */
    public function add($arr) {
        $arr = $this->filter($arr);
        $result = Db()->insert(static::$table, $arr);
        if ($result) {
            return Db()->lastInsertId();
        }
        return false;
    }

    public function update($id, $arr) {
        $arr = $this->filter($arr);
        $where = array($this->_id => $id);
        return Db()->update(static::$table, $arr, $where);
    }

    public function remove($id) {
        $where = array($this->_id => $id);
        return Db()->delete(static::$table, $where);
    }

    public function get($id, $field = '') {
        $where = array($this->_id => $id);
        if ($field != '') {
            return Db()->getOne(static::$table)->fields($field)->where($where)->result();
        }
        return Db()->getRow(static::$table)->where($where)->result();
    }

    public function getc($id, $field = '', $expire = 10) {
        $name = 'record_' . static::$table;
        $row = cache($name, $id);
        if (!$row) {
            $row = $this->get($id);
            cache($name, $id, $row, $expire);
        }
        if ($field != '') {
            return $row[$field];
        }
        return $row;
    }

    public function getAll($offset = null, $length = null, $filter = array(), $order = '') {
        $order || $order = "{$this->_id} desc";
        return Db()->getAll(static::$table)->where($filter)->limit($offset, $length)->order($order)->result();
    }
    
    public function countAll($filter = array()) {
        return Db()->count(static::$table)->where($filter)->result();
    }
    
    public function exportAll($filter = array()) {
        return Db()->getAll(static::$table)->where($filter)->result();
    }

    public function setSort($id, $sort) {
        $data = array($this->_sort => $sort);
        $where = array($this->_id => $id);
        return Db()->update(static::$table, $data, $where);
    }

}
